楠渡余生楠渡余生
首页
笔记
作品集
留言板
关于
GitHub
CSDN
首页
笔记
作品集
留言板
关于
GitHub
CSDN
  • 前端开发

    • React Server Components(RSC)学习笔记

      • React Server Components(RSC)学习笔记
    • 全栈框架学习笔记

      • 全栈框架学习笔记
    • jQuery 学习笔记

      • jQuery 学习笔记
    • React 学习笔记

      • React 学习笔记
    • AJAX 学习笔记

      • AJAX 学习笔记
    • Axios 完整学习笔记

      • Axios 完整学习笔记
    • CSS 属性速查手册

      • CSS 属性速查手册
    • HTML5 与 CSS 综合学习笔记

      • HTML5 与 CSS 综合学习笔记
    • JavaScript 学习笔记

      • JavaScript 学习笔记
    • Promise 学习笔记

      • Promise 学习笔记
    • Tailwind CSS 完整笔记

      • Tailwind CSS 完整笔记
    • TypeScript 快速上手

      • TypeScript 快速上手
    • Vue3 学习笔记

      • Vue3 学习笔记
  • 元框架与全栈路由

    • Next.js App Router 最佳实践

      • Next.js App Router 最佳实践
    • 跨域与服务端组件数据预取

      • 跨域与服务端组件数据预取
  • 现代数据流与安全

    • Prisma Schema 全栈类型生成

      • Prisma Schema 全栈类型生成
    • Supabase RLS 行级安全策略

      • Supabase RLS 行级安全策略
  • 商业化与支付闭环

    • SaaS 订阅制用户表结构设计

      • SaaS 订阅制用户表结构设计
    • Stripe Webhook 接入避坑指南

      • Stripe Webhook 接入避坑指南
  • 零运维与边缘计算

    • Cloudflare 基础防护与 CDN

      • Cloudflare 基础防护与 CDN
    • Vercel 自动化部署与环境变量

      • Vercel 自动化部署与环境变量
  • AI 赋能与集成

    • Vercel AI SDK 流式输出实战

      • Vercel AI SDK 流式输出实战
  • 增长、监控与运营

    • Resend 事务性邮件模板

      • Resend 事务性邮件模板
    • Sentry 前端异常捕获与报警

      • Sentry 前端异常捕获与报警
  • Node.js 深入学习

    • MongoDB 常用命令速查表

      • MongoDB 常用命令速查表
    • Node.js + MongoDB 生产级最佳实践指南

      • Node.js + MongoDB 生产级最佳实践指南
    • Node.js Express 框架

      • Node.js Express 框架
    • Node.js HTTP 模块

      • Node.js HTTP 模块
    • Node.js NPM 包管理

      • Node.js NPM 包管理
    • Node.js 文件系统模块

      • Node.js 文件系统模块
    • Node.js 模块化设计

      • Node.js 模块化设计
  • 后端开发

    • Express 基本使用

      • Express 基本使用
    • Node.js 学习笔记

      • Node.js 学习笔记
    • SpringBoot 完整学习笔记

      • SpringBoot 完整学习笔记
  • 开发工具

    • Windows + WSL + Docker 踩坑与通关指南

      • Windows + WSL + Docker 踩坑与通关指南
    • GitHub 新手完全指南

      • GitHub 新手完全指南
    • 个人博客搭建指南

      • 个人博客搭建指南

jQuery 学习笔记

jQuery 官方文档 | jQuery API 中文文档

一、jQuery 简介

1. jQuery 是什么

  • jQuery 是一个快速、小巧、功能丰富的 JavaScript 库
  • 由 John Resig 于 2006 年发布,其核心理念是 "Write Less, Do More"(写得更少,做得更多)
  • jQuery 极大地简化了 DOM 操作、事件处理、动画效果和 Ajax 交互

💡 理解要点:

  • 库 vs 框架:jQuery 是一个"库",它不会改变你的代码组织方式,只是提供了一组更便捷的工具函数
  • 封装原生 JS:jQuery 本质上是对原生 JavaScript DOM API 的封装和增强,底层仍然是 JS
  • 历史地位:jQuery 曾是前端开发的事实标准(2006-2015),在浏览器兼容性混乱的年代解决了巨大的痛点。如今虽然现代框架(React/Vue)已成为主流,但大量老项目仍在使用 jQuery,了解它依然有价值
  • 现状:新项目一般不再选择 jQuery,但在维护老项目、使用 Bootstrap 4 及以下版本、WordPress 开发等场景中仍然会遇到

2. jQuery 的优势

  • 简洁的语法:用 $ 选择器代替冗长的 document.getElementById() 等
  • 强大的选择器:支持 CSS 选择器、伪类选择器等丰富的元素选取方式
  • 链式调用:大多数方法返回 jQuery 对象本身,支持 .method1().method2().method3() 连续调用
  • 跨浏览器兼容:自动处理 IE、Firefox、Chrome 等浏览器之间的差异
  • 丰富的插件生态:海量的第三方插件可以快速实现轮播图、弹窗、表单验证等功能
  • 隐式迭代:对一组匹配的元素自动遍历执行操作,不需要手动写循环

3. 引入 jQuery

CDN 引入(推荐快速使用)

<!-- 生产环境(压缩版) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>

<!-- 开发环境(未压缩,可调试) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.js"></script>

本地引入

<!-- 下载后放到项目中 -->
<script src="./js/jquery.min.js"></script>

npm 安装

npm install jquery
// 模块化项目中引入
import $ from 'jquery';

4. 入口函数

// 方式一:完整写法
$(document).ready(function () {
    // DOM 加载完成后执行
    console.log('DOM 准备就绪');
});

// 方式二:简写形式(推荐)
$(function () {
    // DOM 加载完成后执行
    console.log('DOM 准备就绪');
});

💡 jQuery 入口函数 vs window.onload:

特性$(function() {})window.onload
执行时机DOM 结构加载完成即执行所有资源(图片等)加载完成后执行
执行速度更快较慢
可绑定多个可以后面的会覆盖前面的

5. $ 符号的本质

// $ 是 jQuery 的别名,两者完全等价
console.log($ === jQuery);  // true

// $ 是一个函数,接收不同类型的参数
$(function () {});           // 传入函数 → 入口函数
$('#box');                   // 传入选择器字符串 → 获取元素
$('<div>新元素</div>');      // 传入 HTML 字符串 → 创建元素
$(document);                 // 传入 DOM 对象 → 转为 jQuery 对象

💡 避免 $ 冲突:如果项目中有其他库也使用了 $,可以使用 jQuery.noConflict() 释放 $,之后用 jQuery 代替 $。

二、选择器

jQuery 的选择器语法与 CSS 选择器一致,这是 jQuery 最强大的特性之一。

1. 基础选择器

$('#id')           // ID 选择器:选取 id="id" 的元素
$('.class')        // 类选择器:选取所有 class="class" 的元素
$('div')           // 标签选择器:选取所有 <div> 元素
$('*')             // 通配选择器:选取所有元素
$('div, p, span')  // 并集选择器:选取所有 div、p、span

2. 层级选择器

$('ul li')         // 后代选择器:ul 内所有的 li(包含孙子辈)
$('ul > li')       // 子代选择器:ul 的直接子元素 li
$('.box + p')      // 相邻兄弟:紧接在 .box 后面的第一个 p
$('.box ~ p')      // 通用兄弟:.box 后面所有的同级 p

3. 过滤选择器

// 基本过滤
$('li:first')         // 第一个 li
$('li:last')          // 最后一个 li
$('li:eq(2)')         // 索引为 2 的 li(从 0 开始)
$('li:odd')           // 奇数索引的 li(1, 3, 5...)
$('li:even')          // 偶数索引的 li(0, 2, 4...)
$('li:gt(2)')         // 索引大于 2 的 li
$('li:lt(2)')         // 索引小于 2 的 li
$(':not(.active)')    // 不含 active 类的元素

// 内容过滤
$('div:contains("Hello")')  // 包含文本 "Hello" 的 div
$('div:empty')               // 没有子元素的 div
$('div:has(p)')              // 包含 p 元素的 div

// 可见性过滤
$('div:visible')     // 可见的 div
$('div:hidden')      // 隐藏的 div

// 表单过滤
$(':input')          // 所有表单元素(input、textarea、select、button)
$(':text')           // type="text" 的 input
$(':password')       // type="password" 的 input
$(':checked')        // 选中的复选框/单选框
$(':selected')       // 选中的 option
$(':disabled')       // 禁用的表单元素
$(':enabled')        // 启用的表单元素

4. 属性选择器

$('input[name]')           // 有 name 属性的 input
$('input[name="user"]')    // name="user" 的 input
$('input[name^="pre"]')    // name 以 "pre" 开头的 input
$('input[name$="fix"]')    // name 以 "fix" 结尾的 input
$('input[name*="mid"]')    // name 包含 "mid" 的 input
$('input[name!="user"]')   // name 不等于 "user" 的 input(jQuery 扩展)

5. jQuery 对象与 DOM 对象的互转

// DOM 对象 → jQuery 对象:用 $() 包裹
const div = document.getElementById('box');
const $div = $(div);       // 现在可以使用 jQuery 方法了
$div.hide();

// jQuery 对象 → DOM 对象:用索引或 get() 方法
const $lis = $('li');
const li1 = $lis[0];      // 方式一:下标取出
const li2 = $lis.get(0);  // 方式二:get() 方法
li1.style.color = 'red';  // 使用原生 DOM API

💡 核心概念:

  • jQuery 对象是一个类数组对象,内部包含一组匹配到的 DOM 元素
  • jQuery 对象只能使用 jQuery 方法,DOM 对象只能使用原生方法,两者不能混用
  • 习惯上给 jQuery 对象变量名加 $ 前缀,如 $box,以便和 DOM 对象区分

三、DOM 操作

1. 获取和设置内容

// html() — 获取/设置 HTML 内容(相当于 innerHTML)
$('#box').html();                         // 获取内容
$('#box').html('<h1>新标题</h1>');         // 设置内容(会解析 HTML 标签)

// text() — 获取/设置纯文本(相当于 innerText)
$('#box').text();                         // 获取纯文本
$('#box').text('纯文本内容');              // 设置纯文本(标签会被转义)

// val() — 获取/设置表单元素的值(相当于 value)
$('input').val();                         // 获取输入框的值
$('input').val('新的值');                  // 设置输入框的值

html() vs text() 对比

方法读取内容设置内容等价原生属性
html()含 HTML 标签会解析 HTML 标签innerHTML
text()仅纯文本不会解析 HTML 标签innerText

2. 属性操作

// attr() — 获取/设置 HTML 属性(操作的是标签上的属性)
$('img').attr('src');                      // 获取 src 属性
$('img').attr('src', 'new.jpg');           // 设置单个属性
$('img').attr({                            // 设置多个属性
    src: 'new.jpg',
    alt: '新图片',
    title: '图片标题'
});
$('img').removeAttr('title');              // 移除属性

// prop() — 获取/设置 DOM 属性(操作的是 DOM 对象的属性)
$(':checkbox').prop('checked');             // 获取选中状态(返回 true/false)
$(':checkbox').prop('checked', true);       // 设置为选中
$(':checkbox').prop('disabled', true);      // 设置为禁用

💡 attr() vs prop():

  • attr() 操作的是 HTML 标签属性(写在标签上的),返回字符串
  • prop() 操作的是 DOM 对象属性(JavaScript 对象的属性),返回对应类型
  • 经验法则:对于 checked、disabled、selected 等布尔属性,用 prop();对于 src、href、class、自定义属性等,用 attr()
  • 如果用 attr() 获取 checked,可能返回 "checked" 或 undefined,而不是 true/false

3. data() — 自定义数据

// 存储数据(不会写到 HTML 标签上,存在 jQuery 内部缓存中)
$('#box').data('index', 5);
$('#box').data('info', { name: '张三', age: 18 });

// 读取数据
$('#box').data('index');     // 5
$('#box').data('info');      // { name: '张三', age: 18 }

// 也可以读取 HTML5 的 data-* 属性
// <div id="box" data-color="red" data-user-name="张三"></div>
$('#box').data('color');     // 'red'
$('#box').data('userName');  // '张三'(自动转为驼峰命名)

// 移除数据
$('#box').removeData('index');

4. 样式操作

// css() — 获取/设置样式
$('#box').css('color');                       // 获取样式值
$('#box').css('color', 'red');                // 设置单个样式
$('#box').css({                               // 设置多个样式
    color: 'red',
    fontSize: '20px',                         // 驼峰写法
    'background-color': '#f0f0f0',            // 或用引号包裹的 CSS 原始写法
    width: 200                                // 数值类型自动加 px
});

// 类名操作
$('#box').addClass('active');                 // 添加类名
$('#box').addClass('active highlight');       // 添加多个类名
$('#box').removeClass('active');              // 移除类名
$('#box').removeClass();                      // 移除所有类名
$('#box').toggleClass('active');              // 切换类名(有则移除,无则添加)
$('#box').hasClass('active');                 // 判断是否有某个类名(返回布尔值)

与原生 classList 的对比

jQuery 方法原生 DOM classList作用
.addClass().classList.add()添加类名
.removeClass().classList.remove()移除类名
.toggleClass().classList.toggle()切换类名
.hasClass().classList.contains()判断类名

5. 尺寸和位置

// 尺寸方法
$('#box').width();           // 内容宽度(不含 padding、border)
$('#box').height();          // 内容高度
$('#box').innerWidth();      // 内容 + padding
$('#box').innerHeight();
$('#box').outerWidth();      // 内容 + padding + border
$('#box').outerHeight();
$('#box').outerWidth(true);  // 内容 + padding + border + margin

// 设置尺寸
$('#box').width(300);        // 设置宽度(数值自动加 px)
$('#box').height('50%');     // 也可以传字符串

// 位置方法
$('#box').offset();          // 相对于文档的偏移 { top: 100, left: 50 }
$('#box').offset({ top: 200, left: 100 });  // 设置偏移
$('#box').position();        // 相对于定位父元素的偏移(只读)
$(window).scrollTop();       // 获取页面滚动距离
$(window).scrollTop(0);      // 滚动到顶部

💡 尺寸方法图解:

┌─────── outerWidth(true) ────────┐
│ margin                          │
│ ┌──── outerWidth() ──────┐      │
│ │ border                 │      │
│ │ ┌── innerWidth() ──┐   │      │
│ │ │ padding           │   │      │
│ │ │ ┌─ width() ──┐   │   │      │
│ │ │ │  content    │   │   │      │
│ │ │ └─────────────┘   │   │      │
│ │ └───────────────────┘   │      │
│ └─────────────────────────┘      │
└──────────────────────────────────┘

四、DOM 节点操作

1. 创建节点

// 创建元素
const $newDiv = $('<div class="item">新元素</div>');
const $newLi = $('<li>').text('列表项').addClass('active');

2. 插入节点

// 内部插入(作为子元素)
$('#list').append('<li>末尾追加</li>');       // 在内部末尾追加
$('#list').prepend('<li>开头插入</li>');      // 在内部开头插入
$('<li>末尾追加</li>').appendTo('#list');     // 反向写法,效果同 append
$('<li>开头插入</li>').prependTo('#list');    // 反向写法,效果同 prepend

// 外部插入(作为兄弟元素)
$('#box').after('<p>后面插入</p>');           // 在元素后面插入
$('#box').before('<p>前面插入</p>');          // 在元素前面插入
$('<p>后面插入</p>').insertAfter('#box');     // 反向写法
$('<p>前面插入</p>').insertBefore('#box');    // 反向写法

插入方法对比

方法位置方向说明
append()内部末尾父 → 子A.append(B) B 加到 A 内部末尾
appendTo()内部末尾子 → 父B.appendTo(A) 同上
prepend()内部开头父 → 子A.prepend(B) B 加到 A 内部开头
prependTo()内部开头子 → 父B.prependTo(A) 同上
after()外部后面参考 → 新A.after(B) B 加到 A 后面
before()外部前面参考 → 新A.before(B) B 加到 A 前面

3. 删除和替换节点

// 删除
$('#box').remove();      // 删除元素本身(包括事件和数据,彻底销毁)
$('#box').detach();      // 删除元素但保留事件和数据(可以重新插入)
$('#box').empty();       // 清空元素的所有子节点(元素本身保留)

// 替换
$('#old').replaceWith('<div>新元素</div>');
$('<div>新元素</div>').replaceAll('#old');      // 反向写法

// 克隆
$('#box').clone();        // 浅拷贝(不复制事件)
$('#box').clone(true);    // 深拷贝(同时复制事件处理函数)

💡 remove() vs detach() vs empty():

  • remove():彻底删除元素,事件和数据一并清除,适合永久删除
  • detach():从 DOM 中移除但保留事件和数据,适合临时移除后重新插入
  • empty():只清空子元素,元素本身保留在 DOM 中

4. 包裹节点

// wrap() — 给每个元素单独包裹一层
$('p').wrap('<div class="wrapper"></div>');
// 结果:每个 p 都被各自的 div 包裹

// wrapAll() — 所有匹配元素用一个元素包裹
$('p').wrapAll('<div class="wrapper"></div>');
// 结果:所有 p 被同一个 div 包裹

// wrapInner() — 包裹元素的内容
$('p').wrapInner('<strong></strong>');
// <p>文本</p> → <p><strong>文本</strong></p>

// unwrap() — 移除父元素(保留自身)
$('p').unwrap();

五、事件处理

1. 事件绑定

// on() — 推荐的事件绑定方式
$('#btn').on('click', function () {
    console.log('按钮被点击了');
});

// 绑定多个事件
$('#box').on({
    mouseenter: function () {
        $(this).addClass('hover');
    },
    mouseleave: function () {
        $(this).removeClass('hover');
    },
    click: function () {
        console.log('点击了');
    }
});

// 同一处理函数绑定多个事件(空格分隔)
$('#box').on('mouseenter mouseleave', function () {
    $(this).toggleClass('hover');
});

2. 事件委托

利用事件冒泡机制,将事件绑定到父元素上,处理子元素的事件。特别适用于动态添加的元素。

// 事件委托:on() 的第二个参数为子元素选择器
$('#list').on('click', 'li', function () {
    // this 指向触发事件的 li,而不是 #list
    $(this).toggleClass('active');
});

// 动态添加的 li 也能响应事件
$('#list').append('<li>新添加的项</li>');  // ✅ 点击同样有效

// ❌ 直接绑定:动态添加的元素无法响应
// $('li').on('click', function () { ... });  // 只对已存在的 li 有效

💡 事件委托的优势:

  • 动态元素:后续添加的子元素自动拥有事件处理能力
  • 性能优化:100 个 li 只需绑定 1 个事件到 ul 上,而不是 100 个
  • 原理:事件冒泡 — 子元素的事件会冒泡到父元素,jQuery 通过 event.target 判断实际触发源

⚠️ 新手坑:回调里不要用箭头函数取 this jQuery 事件回调中的 this 指向触发事件的 DOM 元素,但箭头函数没有自己的 this,会继承外层作用域,导致 $(this) 取不到当前元素。

// ❌ 箭头函数:this 不是当前 li
$('#list').on('click', 'li', () => {
    $(this).addClass('active');  // this 指向外层,通常是 window
});

// ✅ 用普通函数;或用 e.currentTarget 取当前元素
$('#list').on('click', 'li', function (e) {
    $(this).addClass('active');          // 正确
    // $(e.currentTarget).addClass('active'); // 等价写法
});

3. 事件解绑与一次性事件

// off() — 解绑事件
$('#btn').off('click');           // 解绑所有 click 事件
$('#btn').off();                  // 解绑所有事件

// 解绑特定函数
function handleClick() {
    console.log('clicked');
}
$('#btn').on('click', handleClick);
$('#btn').off('click', handleClick);

// one() — 事件只触发一次
$('#btn').one('click', function () {
    console.log('只会执行一次');
});

4. 事件触发

// trigger() — 自动触发事件(会触发冒泡和默认行为)
$('#btn').trigger('click');
$('#btn').click();               // 简写形式

// triggerHandler() — 不触发冒泡和默认行为
$('#form').triggerHandler('submit');

5. 常用事件方法

// 鼠标事件
$('#box').click(fn)          // 单击
$('#box').dblclick(fn)       // 双击
$('#box').mouseenter(fn)     // 鼠标进入(不会冒泡)
$('#box').mouseleave(fn)     // 鼠标离开(不会冒泡)
$('#box').mouseover(fn)      // 鼠标经过(会冒泡)
$('#box').mouseout(fn)       // 鼠标离开(会冒泡)
$('#box').mousemove(fn)      // 鼠标移动
$('#box').hover(enterFn, leaveFn)  // mouseenter + mouseleave 的合写

// 键盘事件
$(document).keydown(fn)      // 按键按下
$(document).keyup(fn)        // 按键松开
$(document).keypress(fn)     // 按键按住(字符键)

// 表单事件
$('input').focus(fn)         // 获得焦点
$('input').blur(fn)          // 失去焦点
$('input').change(fn)        // 值发生变化
$('form').submit(fn)         // 表单提交
$('input').input(fn)         // 实时输入(需用 on 绑定)

// 窗口事件
$(window).scroll(fn)         // 滚动
$(window).resize(fn)         // 窗口大小变化

💡 mouseenter/mouseleave vs mouseover/mouseout:

  • mouseenter/mouseleave:不冒泡,鼠标移入/移出元素本身时触发,移到子元素上不会触发
  • mouseover/mouseout:会冒泡,鼠标移入/移出子元素时也会触发
  • 大多数场景推荐用 mouseenter/mouseleave 或 hover(),行为更符合预期

6. 事件对象

$('#box').on('click', function (e) {
    // 事件对象属性
    e.type;                // 事件类型 'click'
    e.target;              // 触发事件的原始 DOM 元素
    e.currentTarget;       // 绑定事件的 DOM 元素(等价于 this)
    e.pageX;               // 鼠标相对于文档的 X 坐标
    e.pageY;               // 鼠标相对于文档的 Y 坐标
    e.which;               // 按键代码(鼠标或键盘)
    e.data;                // on() 中传递的附加数据
    e.timeStamp;           // 事件触发的时间戳

    // 事件对象方法
    e.preventDefault();    // 阻止默认行为(如阻止链接跳转、表单提交)
    e.stopPropagation();   // 阻止事件冒泡
    return false;          // jQuery 中等价于同时调用上面两个方法
});

六、动画与效果

1. 显示和隐藏

// show() / hide() / toggle()
$('#box').hide();              // 立即隐藏
$('#box').show();              // 立即显示
$('#box').toggle();            // 切换显示/隐藏

// 带动画效果(参数:时长, 缓动, 回调函数)
$('#box').hide(1000);                    // 1000ms 内隐藏
$('#box').show('slow');                  // 'slow'(600ms) / 'normal'(400ms) / 'fast'(200ms)
$('#box').toggle(500, function () {      // 动画完成后的回调
    console.log('动画结束');
});

2. 淡入和淡出

$('#box').fadeIn(500);          // 淡入(透明度 0 → 1)
$('#box').fadeOut(500);         // 淡出(透明度 1 → 0)
$('#box').fadeToggle(500);      // 切换淡入/淡出
$('#box').fadeTo(500, 0.5);    // 渐变到指定透明度(0~1)

3. 滑动

$('#box').slideDown(500);       // 向下展开
$('#box').slideUp(500);         // 向上收起
$('#box').slideToggle(500);     // 切换展开/收起

4. 自定义动画

// animate(目标属性, 时长, 缓动, 回调)
$('#box').animate({
    width: 300,
    height: 200,
    opacity: 0.5,
    left: '+=50',            // 在当前值上增加 50
    fontSize: 24
}, 1000, 'swing', function () {
    console.log('动画完成');
});

// 链式调用:依次执行多个动画(排队)
$('#box')
    .animate({ width: 300 }, 500)
    .animate({ height: 200 }, 500)
    .animate({ opacity: 0.5 }, 500);

💡 animate() 注意事项:

  • 只能对数值属性进行动画(如 width、height、opacity、left、margin 等)
  • 不能对颜色属性进行动画(需要 jQuery UI 或 jQuery Color 插件)
  • 不能对 transform 进行动画(需要插件,或建议用 CSS transition/animation 代替)
  • 缓动函数默认只有 swing(先慢后快再慢)和 linear(匀速),更多需要引入 jQuery UI

5. 停止动画

// stop() — 停止当前动画
$('#box').stop();              // 停止当前动画,后续动画队列继续
$('#box').stop(true);          // 清空动画队列,停在当前位置
$('#box').stop(true, true);    // 清空队列,直接跳到当前动画的终点

// finish() — 立即完成所有排队中的动画
$('#box').finish();

// delay() — 动画延迟
$('#box')
    .fadeOut(500)
    .delay(1000)               // 延迟 1 秒
    .fadeIn(500);

💡 防止动画积累:当用户快速重复触发动画时(如快速 hover),动画会排队堆积。解决方法是在触发动画前调用 stop():

$('#box').hover(
    function () { $(this).stop().slideDown(300); },
    function () { $(this).stop().slideUp(300); }
);

七、Ajax

jQuery 对 Ajax 进行了深度封装,使异步请求变得极其简单。

1. $.ajax() — 完整写法

$.ajax({
    url: '/api/users',           // 请求地址
    type: 'GET',                 // 请求方式:GET / POST / PUT / DELETE
    data: { page: 1, size: 10 }, // 发送的数据
    dataType: 'json',            // 预期返回的数据类型
    timeout: 5000,               // 超时时间(毫秒)
    headers: {                   // 自定义请求头
        'Authorization': 'Bearer xxx'
    },
    beforeSend: function () {
        // 请求发送前执行(可用于显示 loading)
        console.log('正在请求...');
    },
    success: function (data) {
        // 请求成功的回调
        console.log('数据:', data);
    },
    error: function (xhr, status, error) {
        // 请求失败的回调
        console.log('错误:', error);
    },
    complete: function () {
        // 请求完成的回调(无论成功还是失败)
        console.log('请求完成');
    }
});

2. $.get() / $.post() — 简写方法

// $.get(url, data, callback, dataType)
$.get('/api/users', { page: 1 }, function (data) {
    console.log(data);
}, 'json');

// $.post(url, data, callback, dataType)
$.post('/api/login', {
    username: 'admin',
    password: '123456'
}, function (data) {
    console.log(data);
}, 'json');

// $.getJSON() — 专门获取 JSON 数据
$.getJSON('/api/users', function (data) {
    console.log(data);
});

3. 发送 JSON 数据

// POST 发送 JSON 格式的请求体
$.ajax({
    url: '/api/users',
    type: 'POST',
    contentType: 'application/json',       // 设置请求体格式为 JSON
    data: JSON.stringify({                 // 必须手动序列化
        name: '张三',
        age: 18
    }),
    dataType: 'json',
    success: function (data) {
        console.log(data);
    }
});

4. 表单序列化

// serialize() — 将表单数据序列化为 URL 编码字符串
// 结果:"username=admin&password=123456"
const formData = $('form').serialize();

$.post('/api/login', formData, function (data) {
    console.log(data);
});

// serializeArray() — 序列化为对象数组
// 结果:[{ name: "username", value: "admin" }, { name: "password", value: "123456" }]
const formArray = $('form').serializeArray();

5. 全局 Ajax 事件

// 所有 Ajax 请求的全局钩子(适合做统一的 loading 效果)
$(document)
    .ajaxStart(function () {
        // 任何 Ajax 请求开始时触发
        $('#loading').show();
    })
    .ajaxStop(function () {
        // 所有 Ajax 请求完成时触发
        $('#loading').hide();
    })
    .ajaxError(function (event, xhr, settings, error) {
        // 任何 Ajax 请求失败时触发
        console.error('请求失败:', settings.url, error);
    });

💡 jQuery Ajax vs Fetch vs Axios:

特性jQuery AjaxFetch APIAxios
类型jQuery 内置方法浏览器原生 API第三方库
Promise 支持支持(Deferred)原生 Promise原生 Promise
请求/响应拦截全局事件不支持支持
自动 JSON 解析需指定 dataType需手动 .json()自动
错误处理error 回调只拒绝网络错误HTTP 错误也拒绝
适用场景jQuery 项目现代轻量级项目中大型项目(推荐)

八、遍历与查找

1. 遍历方法

// each() — 遍历 jQuery 对象中的每个元素
$('li').each(function (index, element) {
    // index:当前索引
    // element:当前 DOM 元素(不是 jQuery 对象)
    console.log(index, $(element).text());

    // this 也指向当前 DOM 元素
    $(this).css('color', 'red');

    // return false 可以终止遍历(相当于 break)
    // return true 跳过当前项(相当于 continue)
});

// $.each() — 遍历数组或对象(工具方法)
$.each([10, 20, 30], function (index, value) {
    console.log(index, value);  // 0 10, 1 20, 2 30
});

$.each({ name: '张三', age: 18 }, function (key, value) {
    console.log(key, value);    // name 张三, age 18
});

// map() — 遍历并返回新的 jQuery 对象
const texts = $('li').map(function (index, element) {
    return $(element).text();
}).get();  // .get() 转为普通数组

2. 筛选方法

$('li').first();               // 第一个元素
$('li').last();                // 最后一个元素
$('li').eq(2);                 // 索引为 2 的元素(返回 jQuery 对象)
$('li').filter('.active');     // 过滤出匹配选择器的元素
$('li').not('.active');        // 排除匹配选择器的元素
$('li').has('span');           // 保留包含指定后代的元素
$('li').slice(1, 4);          // 截取索引 1 到 3 的元素

3. 查找方法(关系查找)

// 祖先 / 父级
$('#box').parent();                // 直接父元素
$('#box').parents();               // 所有祖先元素
$('#box').parents('.container');    // 匹配选择器的祖先
$('#box').closest('.container');    // 最近的匹配祖先(从自身开始向上找)
$('#box').parentsUntil('.wrapper'); // 向上查找直到匹配为止(不含匹配元素)

// 子级 / 后代
$('#box').children();              // 所有直接子元素
$('#box').children('.item');       // 匹配的直接子元素
$('#box').find('span');            // 所有匹配的后代元素(必须传参数)
$('#box').contents();              // 所有子节点(包括文本节点)

// 兄弟
$('#box').siblings();              // 所有兄弟元素
$('#box').siblings('.active');     // 匹配的兄弟元素
$('#box').next();                  // 下一个兄弟
$('#box').nextAll();               // 后面所有兄弟
$('#box').nextUntil('.end');       // 后面直到匹配为止
$('#box').prev();                  // 上一个兄弟
$('#box').prevAll();               // 前面所有兄弟
$('#box').prevUntil('.start');     // 前面直到匹配为止

💡 parent() vs parents() vs closest():

  • parent():只找直接父元素(一层)
  • parents():找所有祖先元素(一直到 <html>),返回多个
  • closest():从自身开始向上找,返回第一个匹配的祖先(只返回一个),最常用

4. 链式调用

jQuery 大多数方法都返回 jQuery 对象本身,因此可以链式调用:

$('#box')
    .css('color', 'red')
    .addClass('active')
    .slideDown(500)
    .find('p')
    .text('Hello')
    .end()                // 回到上一个 jQuery 对象(即 #box)
    .attr('title', '标题');

💡 end() 方法:在链式调用中,find()、children()、filter() 等方法会改变当前操作的 jQuery 对象。调用 end() 可以回退到上一步的 jQuery 对象,继续操作原来的元素。

九、常用工具方法

1. 类型判断

$.type(123);                  // 'number'
$.type('hello');              // 'string'
$.type([1, 2]);               // 'array'
$.type({});                   // 'object'
$.type(null);                 // 'null'
$.type(undefined);            // 'undefined'

$.isArray([1, 2, 3]);         // true
$.isFunction(function () {}); // true
$.isEmptyObject({});          // true
$.isPlainObject({});          // true(纯粹的对象,非 DOM/jQuery 等)
$.isNumeric('123');           // true
$.isNumeric('abc');           // false

⚠️ 注意:$.type()、$.isArray()、$.isFunction()、$.isNumeric() 等方法在 jQuery 3.3+ 中已被标记为废弃(deprecated),推荐使用原生方法:typeof、Array.isArray()、typeof fn === 'function'、!isNaN() 等。

2. 其他工具方法

// $.trim() — 去除字符串首尾空格(jQuery 3.5+ 废弃,用原生 String.trim())
$.trim('  hello  ');          // 'hello'

// $.extend() — 合并对象
const defaults = { color: 'red', size: 12 };
const options = { color: 'blue', weight: 'bold' };

// 浅合并(修改 defaults)
$.extend(defaults, options);
// defaults → { color: 'blue', size: 12, weight: 'bold' }

// 不修改原对象的写法
const result = $.extend({}, defaults, options);

// 深拷贝合并(第一个参数传 true)
$.extend(true, target, obj1, obj2);

// $.proxy() — 改变函数的 this 指向(类似 Function.bind)
const obj = {
    name: '张三',
    sayHi: function () {
        console.log(this.name);
    }
};
$('#btn').on('click', $.proxy(obj.sayHi, obj));  // this 指向 obj

十、jQuery 插件机制

1. 使用插件的基本流程

<!-- 1. 先引入 jQuery -->
<script src="jquery.min.js"></script>

<!-- 2. 再引入插件文件 -->
<script src="jquery.plugin.min.js"></script>
<link rel="stylesheet" href="jquery.plugin.css" />

<!-- 3. 按照插件文档初始化 -->
<script>
    $(function () {
        $('#element').pluginName({
            option1: value1,
            option2: value2
        });
    });
</script>

2. 自定义插件

// 方式一:$.fn 扩展实例方法(最常用)
$.fn.highlight = function (color) {
    // this 是调用插件的 jQuery 对象
    return this.each(function () {
        $(this).css({
            backgroundColor: color || 'yellow',
            transition: 'background-color 0.3s'
        });
    });
    // 返回 this 以支持链式调用
};

// 使用
$('p').highlight('lightblue').addClass('highlighted');

// 方式二:带默认选项的插件
$.fn.tooltip = function (options) {
    // 合并默认值和用户传入的选项
    const settings = $.extend({
        position: 'top',
        delay: 200,
        bgColor: '#333'
    }, options);

    return this.each(function () {
        const $el = $(this);
        // 插件逻辑...
    });
};

// 使用
$('.tip').tooltip({ position: 'bottom', delay: 500 });

💡 插件开发规范:

  • 始终返回 this(或 this.each(...) 的结果)以支持链式调用
  • 使用 $.extend() 合并默认选项,方便用户自定义
  • 使用 IIFE(立即执行函数)避免污染全局:(function($) { ... })(jQuery);

十一、jQuery 与原生 JS 对照表

在学习 jQuery 的同时,了解对应的原生 JS 写法有助于深入理解:

操作jQuery原生 JavaScript
获取元素$('#id')document.getElementById('id')
获取元素$('.class')document.querySelectorAll('.class')
获取元素$('div')document.querySelectorAll('div')
获取第一个$('div').first()document.querySelector('div')
修改文本$('#el').text('hello')el.textContent = 'hello'
修改 HTML$('#el').html('<b>hi</b>')el.innerHTML = '<b>hi</b>'
修改样式$('#el').css('color', 'red')el.style.color = 'red'
添加类名$('#el').addClass('active')el.classList.add('active')
移除类名$('#el').removeClass('active')el.classList.remove('active')
绑定事件$('#el').on('click', fn)el.addEventListener('click', fn)
解绑事件$('#el').off('click', fn)el.removeEventListener('click', fn)
创建元素$('<div>')document.createElement('div')
追加子元素$('#el').append(child)el.appendChild(child)
删除元素$('#el').remove()el.remove()
显示/隐藏$('#el').show() / .hide()el.style.display = 'block' / 'none'
获取属性$('#el').attr('href')el.getAttribute('href')
遍历$('li').each(fn)document.querySelectorAll('li').forEach(fn)
Ajax$.ajax({ url, success })fetch(url).then(r => r.json())
DOM 加载$(function() {})document.addEventListener('DOMContentLoaded', fn)

💡 学习建议:

  • 如果你正在维护老项目或使用依赖 jQuery 的库(如 Bootstrap 4、WordPress),jQuery 是必备技能
  • 如果你在开发新项目,推荐使用原生 JS(ES6+)或现代框架(React/Vue),它们在性能、架构和生态上都更具优势
  • 理解 jQuery 的设计思想(链式调用、隐式迭代、选择器引擎)对学习其他库和框架也有帮助
最后更新: 2026/6/13 22:15
贡献者: 52nnnn, Claude Opus 4.6